package org.jeecg.modules.gis.controller;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.gis.config.TokenManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/gis/proxy")
public class ProxyController {
    public static final String TEMPLATE = "http://t{s}.tianditu.gov.cn/DataServer?T={T}&X={x}&Y={y}&L={z}&tk={tk}";
    @Autowired
    private TokenManager tokenManager;
    @Autowired
    private RestTemplate gisRestTemplate;

    /**
     * 天地图底图代理
     *
     * @param z 瓦片层级
     * @param x 瓦片 X 坐标
     * @param y 瓦片 Y 坐标
     * @return 天地图底图切片
     */
    @GetMapping("/{layer}/{z}/{x}/{y}")
    public ResponseEntity<byte[]> tdtBaseLayer(@PathVariable("layer") String layer,
                                               @PathVariable("z") String z,
                                               @PathVariable("x") String x,
                                               @PathVariable("y") String y) {
        String tk = tokenManager.getLeastUsedToken("map");
        String url = TEMPLATE
                .replace("{s}", String.valueOf((int) (Math.random() * 3))) // 随机选择子域 0~2
                .replace("{T}", layer)
                .replace("{z}", z)
                .replace("{x}", x)
                .replace("{y}", y)
                .replace("{tk}", tk);
        //设置header信息
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("User-Agent", "Mozilla/5.0"); // 天地图有可能校验 UA
        //封装信息
        HttpEntity requestEntity = new HttpEntity(null, requestHeaders);

        ResponseEntity<byte[]> exchange = gisRestTemplate.exchange(url, HttpMethod.GET, requestEntity, byte[].class);
        log.info(url);
        return exchange;

    }

    /**
     * 天地图地理编码代理
     *
     * @param keyWord 地名关键字
     * @return 经纬度信息
     */
    @GetMapping("/tdtGeocoder")
    public ResponseEntity<byte[]> tdtGeocoder(@RequestParam("keyWord") String keyWord) {
        String tk = tokenManager.getLeastUsedToken("geocode");

        // 如果天地图接口需要的参数是 JSON 字符串格式放在 ds 里，先组装 JSON 字符串
        JSONObject params = new JSONObject();
        params.put("keyWord", keyWord);
        String dsJsonStr = params.toString();

        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://api.tianditu.gov.cn/geocoder")
                .queryParam("ds", dsJsonStr)
                .queryParam("tk", tk);

        String url = builder.toUriString();
        //设置header信息
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("User-Agent", "Mozilla/5.0"); // 天地图有可能校验 UA
        //封装信息
        HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
        ResponseEntity<byte[]> response = gisRestTemplate.exchange(url, HttpMethod.GET, requestEntity, byte[].class);
        return response;
    }

    /**
     * 天地图逆地理编码代理
     *
     * @param lng 经度
     * @param lat 纬度
     * @return 经纬度信息
     */
    @GetMapping("/tdtUnGeocoder")
    public ResponseEntity<byte[]> tdtUnGeocoder(@RequestParam("lng") String lng, @RequestParam("lat") String lat) {
        String tk = tokenManager.getLeastUsedToken("geocode");

        // 如果天地图接口需要的参数是 JSON 字符串格式放在 ds 里，先组装 JSON 字符串
        JSONObject params = new JSONObject();
        params.put("lon", lng);
        params.put("lat", lat);
        params.put("ver", 1);
        String dsJsonStr = params.toString();

        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://api.tianditu.gov.cn/geocoder")
                .queryParam("postStr", dsJsonStr)
                .queryParam("type", "geocode")
                .queryParam("tk", tk);

        String url = builder.toUriString();
        //设置header信息
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("User-Agent", "Mozilla/5.0"); // 天地图有可能校验 UA
        //封装信息
        HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
        ResponseEntity<byte[]> response = gisRestTemplate.exchange(url, HttpMethod.GET, requestEntity, byte[].class);
        return response;
    }

    /**
     * 天地图地名搜索代理
     *
     * @param keyWord   搜索的关键字
     * @param queryType 服务查询类型参数
     * @param queryType 返回结果起始位
     * @param queryType 返回结果起始位
     * @return 地名信息
     */

    @GetMapping("/tdtSearch")
    public ResponseEntity<byte[]> tdtSearch(
            @RequestParam(value = "keyWord", defaultValue = "") String keyWord,
            @RequestParam(value = "queryType", defaultValue = "1") int queryType,
            @RequestParam(value = "start", defaultValue = "0") int start,
            @RequestParam(value = "count", defaultValue = "10") int count,
            @RequestParam(value = "specify", defaultValue = "") String specify,
            @RequestParam(value = "mapBound", defaultValue = "118.856,38.722,125.871,43.480") String mapBound,
            @RequestParam(value = "level", defaultValue = "11") int level
    ) throws URISyntaxException {

        String tk = tokenManager.getLeastUsedToken("search");

        // 构造 JSON 参数对象
        JSONObject params = new JSONObject();
        params.put("keyWord", keyWord);
        if (specify != null && !specify.isEmpty()) {
            params.put("specify", specify);// 字符串非空
        }


        params.put("level", level);
        params.put("mapBound", mapBound);
        params.put("queryType", queryType);
        params.put("count", count);
        params.put("start", start);
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://api.tianditu.gov.cn/v2/search")
                .queryParam("postStr", params)
                .queryParam("type", "query")
                .queryParam("tk", tk);

        String url = builder.toUriString();
        log.info("请求天地图 URL: {}", url);
        // 构造请求，避免 URI 编码被 RestTemplate 处理
        RequestEntity<Void> requestEntity = RequestEntity
                .get(new URI(url)) // 手动构造 URI
                .header("User-Agent", "Mozilla/5.0") // 天地图有可能校验 UA
                .build();
        return gisRestTemplate.exchange(requestEntity, byte[].class);
    }

    @GetMapping("/get")
    public ResponseEntity<byte[]> proxyGet(
            @RequestParam("url") String targetUrl,                  // 目标地址
            @RequestParam Map<String, String> allParams,           // 所有请求参数
            @RequestHeader Map<String, String> headers) {          // 所有请求头

        // 删除代理中用作控制的参数 "url"，避免传递到目标地址
        allParams.remove("url");

        // 构建目标 URL，并拼接所有参数
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(targetUrl);
        allParams.forEach(builder::queryParam); // 将请求参数加入 URL 中


        //设置header信息
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("User-Agent", "Mozilla/5.0"); // 天地图有可能校验 UA
        //封装信息
        HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
        ResponseEntity<byte[]> response = gisRestTemplate.exchange(builder.toUriString(), HttpMethod.GET, requestEntity, byte[].class);
        return response;

    }

    /**
     * 通用 POST 请求代理
     * 示例：POST /proxy/post?url=http://xxx.com/api
     * Body: {"key": "value"}
     */
    @PostMapping("/post")
    public ResponseEntity<String> proxyPost(
            @RequestParam("url") String targetUrl,                  // 目标地址
            @RequestBody(required = false) String body,            // 原始请求体 JSON
            @RequestHeader Map<String, String> headers) {          // 请求头

        // 构建代理请求头
        HttpHeaders proxyHeaders = new HttpHeaders();
        headers.forEach(proxyHeaders::add);

        // 默认 Content-Type 设置为 application/json
        proxyHeaders.setContentType(MediaType.APPLICATION_JSON);

        // 构建包含 body 和 header 的请求实体
        HttpEntity<String> entity = new HttpEntity<>(body, proxyHeaders);

        // 发送 POST 请求
        return gisRestTemplate.exchange(
                targetUrl,
                HttpMethod.POST,
                entity,
                String.class
        );
    }

}
